import asyncio
import websockets
import cv2
import base64
import json
import logging
# import speech_recongition as sr
from collections import Counter


# 配置 logging 模块，将日志记录保存到文件中
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='close_eye.log',  # 日志文件名
    filemode='w'  # 写入模式，'w' 表示覆盖写入，'a' 表示追加写入
)

cloud_uri = ["ws://202.114.212.194:50511/detect", "ws://202.114.212.193:50511/detect"]
front_video_uri = ["ws://10.21.190.171:7979?client_id=client1"]
front_status_uri = "ws://10.21.190.171:6868?client_id=client1"
window_size = 30
step = 10

#test_video = "D:\\CS_COURSE\SoftwareEngineering\Test\\close_eye.mp4"
def save_image(buffer, filename):
    with open(filename, "wb") as f:
        f.write(buffer)

async def capture_camera(queue1, queue2):
    
        cap = cv2.VideoCapture(0)
        try:
            while cap.isOpened() :
                ret, frame = cap.read()
                if not ret:
                    print("Failed to read frame")
                    break

                # 编码图片为 Base64
                _, buffer = cv2.imencode('.jpg', frame)
                # save_image(buffer, "test.jpg")
                img_str = base64.b64encode(buffer)
                await queue1.put(img_str)
                await queue2.put(img_str)
                await asyncio.sleep(0.01)  # 主动交出控制权，避免阻塞
        finally:
            cap.release()
            #终止整个程序
            logging.info("Video capture finished, stopping event loop")
            asyncio.get_event_loop().stop()  # 停止事件循环

async def video_websocket(URI_list, queue, send_queue = None):
    URI = URI_list[0]
    curURI = 0
    key = "cloud" if URI == cloud_uri[0] else "front"
    window = []
    while True:
        print(f"Connecting to {key}")
        try:
            async with websockets.connect(URI) as websocket:
                print(f"Successfully Connected to {key}")
                while True:
                    img_str = await queue.get()  # 从队列中获取图片数据
                    await websocket.send(img_str)
                    #print(f"Sent frame to server: {key} ")
                    #logging.info(f"Sent frame to server: {key} num for the server : {cnt}")
                    if URI in cloud_uri:
                        # 接收服务器返回的推理结果
                        response = await websocket.recv()
                        if(isinstance(response, str)):
                            result = json.loads(response)
                            window.append(result['detected_class'])
                            #print(f"Received result from cloud: {result['detected_class']}")
                            #logging.info(f"Received result from cloud: {result['detected_class']}")
                        if len(window) == window_size:
                            counter = Counter(window)
                            most_common, _ = counter.most_common(1)[0]
                            await send_queue.put(most_common)  # 将结果放入队列
                            #print(f"Sent result to status: {most_common}")
                            #logging.info(f"Sent result to status: {most_common}")
                            window = window[step:]
        except websockets.ConnectionClosed:
            print(f"Connection to {key} closed")
        except Exception as e:
            print(f"Failed to connect to {key} : {e}")
   
        if len(URI_list) > 1:
            curURI = (curURI + 1) % len(URI_list)
            URI = URI_list[curURI]
            print(f"Switching to {URI}")
        await asyncio.sleep(0.1)

async def status_websocket(URI, queue):
    key = "status"
    print(f"Connecting to {key}")
    try:
        async with websockets.connect(URI) as websocket:
            while True:
                status = await queue.get()
                await websocket.send(str(status))
    except Exception as e:
        print(f"Failed to connect to {key} : {e}")


async def main():
    queue_cloud = asyncio.Queue(maxsize=10)
    queue_front = asyncio.Queue(maxsize=10)
    queue_status = asyncio.Queue(maxsize=10)
    await asyncio.gather(
        capture_camera(queue_cloud, queue_front),
        video_websocket(cloud_uri, queue_cloud, queue_status),
        video_websocket(front_video_uri, queue_front),
        status_websocket(front_status_uri, queue_status)
    )

asyncio.run(main())